//////////////////////////////////////////////////////////////////////////
// $Id: Dict.cpp,v 1.1 2009/04/03 12:46:10 sunjun Exp $
//////////////////////////////////////////////////////////////////////////

#include "Local.h"

//////////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////////

NAMESPACE_BEGIN

//////////////////////////////////////////////////////////////////////////

	INLINE Dict::Key::Key(const CHAR*name, MReference* ptr)
	{
		CHECK(name&&ptr);
		mName = name;
		mPtr = ptr;				
		Dict::instance().add( name, this );
	}

	INLINE Dict::Key::~Key()
	{
		Dict::instance().remove( mName.c_str() );
		if(mPtr) mPtr.release();
	}

	/*
	====================
	ptr
	====================
	*/
	INLINE MReference* Dict::Key::ptr()
	{
		return mPtr.ptr();
	}

	//////////////////////////////////////////////////////////////////////////

	INLINE Dict::Dict()
	{

	}

	INLINE Dict::~Dict()
	{
		for( std::map< Str, Key* >::iterator it = mKeys.begin(); it != mKeys.end(); ++it ) 
		{
			MAssert( VA("The key(%s) isn`t released.", it->first.c_str() ) );
		}
	}

	/*
	====================
	instance
	====================
	*/
	INLINE Dict& CDECL Dict::instance()
	{
		static Dict s_dict;
		return s_dict;
	}

	/*
	====================
	find
	====================
	*/
	INLINE Dict::Key* Dict::find( const CHAR*name )
	{
		std::map< Str, Key* >::iterator it = mKeys.find(name);
		if(it == mKeys.end()) return NULL;
		return it->second;
	}

	/*
	====================
	add
	====================
	*/
	INLINE VOID Dict::add( const CHAR*name, Key* key )
	{
		if(mKeys.find(name) != mKeys.end()) MAssert( VA("The key(%s) is existent already!", name ) );
		mKeys.insert( std::map< Str, Key* >::value_type( name, key ) );
	}

	/*
	====================
	remove
	====================
	*/
	INLINE VOID Dict::remove( const CHAR*name )
	{
		std::map< Str, Key* >::iterator it = mKeys.find(name);
		if(it == mKeys.end()) MAssert( VA("Can`t find the key : %s.", name ) );
		mKeys.erase(it);
	}

//////////////////////////////////////////////////////////////////////////

#if 0
	// this class provides an object-oriented dict interface.
	template<class T>
	class Dict
	{
	public:
		template<class T> struct type {};		

		template<class T>
		class Key : public MReference
		{
		public:
			// constructor
			INLINE Key(const CHAR*name, T* ptr)
			{
				CHECK(name&&ptr);
				mName = name;
				mPtr = ptr;
				static type<T>null_type;
				Dict<T>::instance(null_type).add( name, this );
			}

			// destructor
			INLINE ~Key()
			{
				static type<T>null_type;
				Dict<T>::instance(null_type).remove( mName.c_str() );
				if(mPtr) mPtr.release();
			}

			// get the pointer
			INLINE T* ptr()
			{
				return mPtr.ptr();
			}

		private:
			Str mName; MPtr<T>mPtr;
		};

	public:
		// constructor
		INLINE Dict()
		{
		}

		// destructor
		INLINE ~Dict()
		{
		}

		// get
		INLINE Key<T>* get( const CHAR*name )
		{
			std::map< Str, Key<T>* >::iterator it = mKeys.find(name);
			if(it == mKeys.end()) return NULL;
			return it->second;
		}

	private:
		// add
		INLINE VOID add( const CHAR*name, Key<T>* key )
		{
			if(mKeys.find(name) != mKeys.end()) MAssert( VA("The key(%s) is existent already!", name ) );
			mKeys.insert( std::map< Str, Key<T>* >::value_type( name, key ) );
		}

		// remove		
		INLINE VOID remove( const CHAR*name )
		{
			std::map< Str, Key<T>* >::iterator it = mKeys.find(name);
			if(it == mKeys.end()) MAssert( VA("Can`t find the key : %s.", name ) );
			mKeys.erase(it);
		}

	public:
		template<class T>
		INLINE static Dict<T>& CDECL instance(type<T>&)
		{
			static Dict<T>s_dict;
			return s_dict;
		}

	private:
		std::map< Str, Key<T>* >mKeys;
	};
#endif

//////////////////////////////////////////////////////////////////////////

NAMESPACE_END

//////////////////////////////////////////////////////////////////////////

